/*************************************************************************************
 Move Networks Geofiltering Library

 Geofiltering expressions limit the availability of content based on the physical
 location of the user requesting the content.  This utility library evaluates
 geofiltering expressions in the context of the user's physical location and determines
 whether or not the user has permission to view the content.

 A geofiltering expression is simply a boolean expression whose
 operands are location expressions of the following form:

 [city|region|country|dma] or [city|region|country] (dma is optional)

 A location expression can contain * wildcards:

 [american fork|ut|usa] - The city of American Fork, UT (ignore DMA information)
 [*|*|*|720] - DMA market 720
 [*|*|usa|*] - Any location within the U.S.A.
 [*|*|*|*] - Any location (this is equivalent to a blank geofiltering expression)

 A geofiltering expression takes the following example form:

 [*|*|mex|*] or ([*|*|usa|*] and not [*|ut|usa|*])
	- Viewing allowed if and only if the user is in Mexico or in a U.S. state
	  other than Utah

 Allowed operators: and, or, not (case insensitive)

 NOTE: Requires movenetworks.js, qvtedit.js

*****************************************************************************************/

MN.Geo =
{

    Init : function(geoserverUrl)
    {
        // Transfer user to the geoserver to get the location cookie set
        if(document.cookie.indexOf('videovalid') == -1)
    	{
    	    url = location.href;
			url = MN.URL.SetParams(geoserverUrl, {'redir':url});
            location.href = url;
	    }
	    log("User Geo Location: " + MN.Cookie.Get("videovalid"));
	    return true;
    },

    // Wraps a geo-filtering expression into a function that can be fed a location string
    // to evaluate.
    MakeFilteringFunc : function(filterExpr)
    {
        filterExpr = filterExpr.strip();
    	var f = function(locStr) {
    	    var jsExpr = filterExpr; // This will hold the rewritten expression that can be evaluated by JS

    	    // An empty or global filter means everything is allowed
    	    if(!filterExpr || filterExpr == "[*|*|*|*]" || filterExpr == "[*|*|*]") return true;

    	    // An empty/invalid location means the user is not allowed
    	    if(!locStr || !locStr.match(/.+\|.+\|.+\|.+/))
    	    {
    	        logError("Geofiltering location empty or invalid: " + locStr);
    	        return true;
    	    }

    	    // Evaluate the location in context of each location expression
    	    var locExprs = filterExpr.match(/\[[^\]]*]/g);
    	    if(!locExprs) return false;  // An invalid filter means "no" for every location
    	    for (var i=0; i < locExprs.length; i++) {
    	        var match = true;
    	        var locCodes = locStr.replace(/[\[\]]/g,"").split("|");
    	        var filterCodes = locExprs[i].slice(1,-1).split("|");
    	        for (var j=0; j < filterCodes.length; j++) {
    	            if(filterCodes[j] != "*" && filterCodes[j] != locCodes[j])
    	            {
    	                match = false;
    	                break;
    	            }
    	        };
    	        // replace the location expression with the match result
    	        jsExpr = jsExpr.replace(locExprs[i], match);
    	    };
    	    // replace the natural lang operands w/ JS operands
            jsExpr = jsExpr.replace(/and/gi, "&&");
            jsExpr = jsExpr.replace(/or/gi, "||");
            jsExpr = jsExpr.replace(/not/gi, "!");

    	    // finally, evaluate the boolean JS expression
    	    var allowed;
    	    try
    	    {
    	        allowed = !!eval(jsExpr);
    	    }
    	    catch(e) // If the evaluation fails, the answer is "no"!
    	    {
    	        logError("Geofiltering expression evaluation failed: " + e);
    	        allowed = true;
    	    }
    	    return allowed;
    	};
    	return f;
    },

    // Returns whether or not a location is allowed according to the geofilter expression
    IsLocationAllowed : function(locStr, filterExpr)
    {
    	f = MN.Geo.MakeFilteringFunc(filterExpr);
    	return f(locStr);
    },

    // Pulls out the user's location from the cookie and runs it against the geofilter expression
    IsUserAllowed : function(filterExpr)
    {
        var locStr = MN.Cookie.Get("videovalid");
        return MN.Geo.IsLocationAllowed(locStr, filterExpr);
    },

    CanUserViewShow : function(showObj)
    {
        if(!showObj.geofilter) return true;
        return MN.Geo.IsUserAllowed(showObj.geofilter);
    },

    // Geofilters a QVT.  Looks for geofilter on each show.  If the user does not pass
    // the geofilter then the content for that show is replaced.  If fillUrl is specified
    // the the show's content is replaced with that QMX URL.  If it's not specified then
    // the content is replaced with a gap.
    //
    // Additionally, a piece of metadata is added to each show to indicate whether or
    // not the user passed the geofilter.
    // geoAllowed = true - if user passed filter and is allowed to watch
    //
    // NOTE: Requires qvtedit.js
    GeofilterQVT : function(qvt, fillUrl)
    {
        if(qvt.shows)
        {
            for (var i=0; i < qvt.shows.length; i++) {
                var show = qvt.shows[i];
                if(!MN.Geo.CanUserViewShow(show))
                {
                    show.geoAllowed = false;
                    MN.QVTEdit.SetShowContentURL(qvt, i, fillUrl);
                }
                else
                {
                    show.geoAllowed = true;
                }
            };
        }
        return qvt;
    }
};